package com.gyj.zookeeper.Watcher;

import com.gyj.zookeeper.Hot.EventHandler;
import com.gyj.zookeeper.Hot.Util.DateFunction;
import com.gyj.zookeeper.Hot.Util.ZookeeperUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;

import static org.apache.logging.log4j.LogManager.exists;

/**
 * Created by Gao on 2018/10/30.
 */
public class WatcherTest {

    private static ZooKeeper zk = null;

    private static ZookeeperUtil util = new ZookeeperUtil();

    private static final Log LOG = LogFactory.getLog(WatcherTest.class);

    public void addLinstener(String nodePath, int type, EventHandler handler) throws Exception {
        LatchChildWatcher latchChildWatcher = new LatchChildWatcher(handler);
        if (type == ZookeeperUtil.NODE_DELETE) {  //nodeChildrenChanged子节点变化
            System.out.println("子节点变化。。。。。。。。");
            try {
                List<String> children = zk.getChildren(nodePath, latchChildWatcher);
                System.out.println(children);  //[node4, node5, node555, node6]子节点
            } catch (KeeperException e) {
                if (e.code().name().equalsIgnoreCase("NONODE")) {
                    return;
                } else {
                    throw e;
                }
            }
        } else {
            Stat exists = zk.exists(nodePath, latchChildWatcher);
        }
        latchChildWatcher.await();
        // 事件监听成功后继续监听
        //addLinstener(nodePath, type, handler);
    }

    private void testListen() {
        try {
           /* String path = "/node8";
            boolean isNodeExist;
            String[] zkChilds = path.split("/");
            String curChild = "";
            for (String child : zkChilds) {
                if (StringUtils.isNotBlank(child)) {
                    curChild = curChild + "/" + child;
                    isNodeExist = exists(curChild);
                    if (!isNodeExist) {
                        createNode(curChild, "", 0);
                    }
                }
            }

            //String child = new Date().getTime() + "#" + 2;
            String child = "node2";
            String zkChild = path + "/" + child;*/
            util.createNode("/node9", "智思数据", 0);  //创建节点，发送请求
            util.createNode("/node9/node1", "智思数据", 0);  //创建节点，发送请求

            //监听在"/node"最近的路径下的子节点的变化，包括创建和删除节点; 如果是"/node/node1"可以，但是"node/node1/node11"是不行的
            addLinstener("/node9", 2, new EventHandler() {
                /* @Override
                 public void nodeDelete(String path) throws Exception {
                     //如果删除的是根节点，则会打印下面的语句
                     System.out.println("节点被删除了（删除的是根节点应该是）。。。");
                 }*/
                @Override
                public void childChange(String path) throws Exception {
                    System.out.println("子节点变化, 监听的是删除子节点。。。");
                    System.out.println("拷贝文件开始。。。");
                    System.out.println(util.getChildren(path));
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //现在的问题是如果在一次定时任务时间内，监测没有触发，则程度会一直阻塞，不会进入下面的循环
    private void TimerTest(int hour) {
        Date startTime = DateFunction.getDateBySet(null, null, null, hour, 10, 0, 0);//每天1点10分
        new Timer().schedule(new TimerTask() {
            public void run() {
                LOG.info("定时开始startTime:" + startTime);
                System.out.println("定时开始startTime:" + startTime);
                testListen1();
                System.out.println("666");
            }

        }, startTime, 1000 * 300);
    }

    public static void main(String[] args) {

        //TimerTest(10);
        //util.testListen1();
    }

    private void testListen1() {

        for (int i = 0; i < 100; i++) {
            try {
                //createNode("/node9", "智思数据", 0);  //创建节点，发送请求
                util.createNode("/node9/" + i, "智思数据", 0);  //创建节点，发送请求
                addListen("/node9");
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("i:" + i);
        }
    }

    private void addListen(String nodePath) {
        LatchChildWatcher1 childWatcher1 = new LatchChildWatcher1();
        try {
            List<String> children = zk.getChildren(nodePath, childWatcher1);
            System.out.println(children);
            childWatcher1.await();
        } catch (InterruptedException | KeeperException e) {
            e.printStackTrace();
        }
    }

    private class LatchChildWatcher1 implements Watcher {

        private CountDownLatch latch;

        public LatchChildWatcher1() {
            latch = new CountDownLatch(1);
        }

        public void process(WatchedEvent event) {
            try {
                System.out.println("type:" + event.getType() + ", path:" + event.getType() + ", state:" + event.getState());
                switch (event.getType()) {
                    case None: {
                        break;
                    }
                    //为什么现在子节点删除的时候，还会继续监听
                    case NodeChildrenChanged: {
                        System.out.println("监听到了子节点变化");
                        break;
                    }
                }
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void await() throws InterruptedException {
            latch.await();
        }
    }

    private class LatchChildWatcher implements Watcher {
        private CountDownLatch latch;
        EventHandler handler;

        public LatchChildWatcher(EventHandler handler) {
            latch = new CountDownLatch(1);
            this.handler = handler;
        }

        public void process(WatchedEvent event) {
            try {
                String path = event.getPath();
                //type:NodeChildrenChanged, path:NodeChildrenChanged, state:SyncConnected
                System.out.println("type:" + event.getType() + ", path:" + event.getType() + ", state:" + event.getState());
                switch (event.getType()) {
                    case None: {
                        break;
                    }
                    //如果删除根节点会输出 type:NodeDeleted, path:NodeDeleted, state:SyncConnected
                   /* case NodeDeleted: {
                        handler.nodeDelete(path);
                        break;
                    }*/
                    //为什么现在子节点删除的时候，还会继续监听
                    case NodeChildrenChanged: {
                        handler.childChange(path);
                        System.out.println("监听到了子节点变化");
                        break;
                    }
                }
                System.out.println("count:" + latch.getCount());
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void await() throws InterruptedException {
            latch.await();
        }
    }


    private void ZkTest() throws Exception {

        ZookeeperUtil.initZkConnection();
        //String[] ZK_PATHS = {"/IssueChildTest/Hot/HotTest", "/IssueChildTest/Hot/HotPro"};
        String zkChildDirectory = "/IssueChildTest/Hot/HotPro1";
        boolean isNodeExist;
        String[] zkChilds = zkChildDirectory.split("/");
        String curChild = "";
        for (String child : zkChilds) {
            if (StringUtils.isNotBlank(child)) {
                curChild = curChild + "/" + child;
                isNodeExist = util.exists(curChild);
                System.out.println(curChild);
                if (!isNodeExist) {
                    util.createNode(curChild, "", 0);
                }
            }
        }

        String child = 111 + "#" + 2;
        String zkChild = zkChildDirectory + "/" + child;
        boolean isNodeExist1 = exists(zkChild);
        if (!isNodeExist1) {
            boolean isCreate = util.createNode(zkChild, "111", 0);
            if (isCreate) {
                LOG.info("节点创建成功！节点路径：" + zkChild);
                String data = util.getData(zkChildDirectory);
                System.out.println("data:" + data);
                data = data + (StringUtils.isNotBlank(data) ? "," : "") + child;
                setData(zkChildDirectory, data);
            }
        }

    }

    public synchronized void setData(String nodePath, String content) throws Exception {
        try {
            zk.setData(nodePath, Bytes.toBytes(content), -1);
            if (LOG.isInfoEnabled()) {
                LOG.info("setData:" + nodePath);
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error(e.getMessage(), e);
            }
            throw e;
        }
    }
}
